#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <malloc.h>
#include <locale.h>

FILE          *dictfd = NULL;
FILE          *dictindexfd = NULL;
char          *dict = NULL;
int           *dictindex = NULL;
int            dictsize = 0;
int            dictentries = 0;

void           fatal(char *msg1, char *msg2)
{
   fprintf(stderr, msg1, msg2);
   exit(2);
}

int            file_length(FILE * fd)
{
   struct stat    stat_buf;

   if (fstat(fileno(fd), &stat_buf) != -1)
      return (stat_buf.st_size);
   return (-1);
}

void          *mmapfile(FILE * fd, int *n)
{
   if (!fd)
      return (fd);
   *n = file_length(fd);
   return (mmap(NULL, *n, PROT_READ,
		MAP_PRIVATE, fileno(fd), 0));
}

void           usage()
{
   fatal("usage: lookup dictionaryfile < input > output\n", NULL);
}

char          *transcribe(text)
     char          *text;
{
   char          *p;
   int            start, end, i;
   int            result;


/* binary dictionary search */
   start = 0;
   end = dictentries - 1;
   while (start < end) {
      i = (start + end) / 2;
      p = dict + dictindex[i];
      result = strcmp(text, p);
      if (result == 0)
	 start = end = i;
      else if (result < 0)
	 end = i;
      else
	 start = i + 1;
   }


/* if search failed, try search with downcased initial letter (but  obviously

 * only if the word starts with a capital one). This is done because of

 * capitalization at the beginning of a  sentence. */
   if ((result != 0) && (isupper(text[0])
			 || (('"' == text[0]) && isupper(text[1])))) {
      if ('"' == text[0])
	 text[1] = tolower(text[1]);
      else
	 text[0] = text[0] + 0x20;	/* tolower and setlocale to iso 8859-1
					   * do not work with flex under
					   solaris. */
      start = 0;
      end = dictentries - 1;
      while (start < end) {
	 i = (start + end) / 2;
	 p = dict + dictindex[i];
	 result = strcmp(text, p);
	 if (result == 0)
	    start = end = i;
	 else if (result < 0)
	    end = i;
	 else
	    start = i + 1;
      }
      if ('"' == text[0])
	 text[1] = toupper(text[1]);
      else
	 text[0] = text[0] - 0x20;
   }
   if (result == 0) {
      p = strchr(p, 0);
      p++;			/* skip key field */
      return p;
   } else
      return text;
}

main(argc, argv)
     int            argc;
     char         **argv;
{
   int            i;
   char           filename[1000];

   ++argv;
   --argc;			/* skip over program name */

   if (argc < 1)
      usage();


/* map dictionary into memory */
   sprintf(filename, "%s", argv[0]);
   dictfd = fopen(filename, "r");
   if (!dictfd)
      fatal("open failed on %s", filename);
   dict = mmapfile(dictfd, &dictsize);


/* map index into memory */
   sprintf(filename, "%s.idx", argv[0]);
   dictindexfd = fopen(filename, "r");
   if (!dictindexfd)
      fatal("open failed on %s", filename);
   dictindex = mmapfile(dictindexfd, &dictentries);
   dictentries /= sizeof(int);

   ++argv;
   --argc;			/* skip over parameter */

   for (i = 1; i < dictentries - 1; i++) {
      if (0 < strcmp(dict + dictindex[i - 1], dict + dictindex[i])) {
	 printf("'%s' seems to be larger as '%s'\n", dict + dictindex[i - 1], dict + dictindex[i]);
      }
   }
}
